﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
using ProtocolBuilder.Model.Field;

namespace ProtocolBuilder
{
    class StorageManager
    {
        public static void SaveAsHtml(string path, XDocument document)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            string name = document.Root.Attribute("name").Value;
            string file = Path.Combine(path, name + ".html");
            using (FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write))
            {
                using (StreamWriter wr = new StreamWriter(fs))
                {
                    IEnumerable<XElement> packets = document.Root.Elements("packet");
                    wr.WriteLine("<html>");
                    wr.WriteLine("<head>");
                    wr.WriteLine("<title>Protocol Document</title>");
                    wr.WriteLine("<script type=\"text/javascript\">function alternativeVisible(id) { var element = document.getElementById(id); var current = element.style.display;element.style.display = current == \"none\" ? \"block\" : \"none\"; }    </script>");
                    wr.WriteLine("<style type=\"text/css\">");
                    wr.WriteLine("div{padding:20px;}");
                    wr.WriteLine("</style>");
                    wr.WriteLine("</head>");

                    wr.WriteLine("<body>");
                    wr.WriteLine("<h2>{0}</h2>", name);
                    wr.WriteLine("<ul>", name);
                    foreach (XElement packetElement in packets)
                    {
                        //<li><a href="#ping">Ping</a></li>
                        wr.WriteLine("<li><a href='#{0}'>{0}(0x{1:x4})</a></li>", packetElement.Attribute("name").Value, int.Parse(packetElement.Attribute("id").Value));
                    }
                    wr.WriteLine("</ul>");

                    int packetPoint = 0;
                    foreach (XElement packetElement in packets)
                    {
                        Packet packet = Packet.FromXml(packetElement);
                        wr.WriteLine("<div>");
                        //wr.WriteLine("<div style=\"display: inline-table\">");
                        wr.WriteLine("<div>");
                        wr.WriteLine("<a name='{0}'><b>{0}(0x{1:x4})</b></a>", packet.PacketName, packet.ID);
                        wr.WriteLine("<p>{0}</p>", packet.Description.TransferToHtmlContent());
                        wr.WriteLine(GenerateHtmlTable(packetElement, null));
                        wr.WriteLine("</div>");

                        /*
                         <div style="display: inline-table">
                         * <p>readcode</p>
                         * <div id="packet1w">
                         * getString();<br />
                         * getInt();<br />
                         * getInt();
                         * </div>
                         * </div>
                         */
                        //Serialize
                        wr.WriteLine("<div>");
                        string divID = string.Format("packet{0}w", packetPoint);
                        wr.WriteLine("<a onclick=\"alternativeVisible('" + divID + "');\"  href=\"javascript:void(0)\">序列化代码</a>");
                        wr.WriteLine("<div id=\"{0}\" style=\"display:none\">", divID);
                        foreach (AbsField field in packet.GenerateFieldList())
                        {
                            wr.WriteLine("{0}{1}", field.GenerateSerializeCode(), TextHelper.HtmlNewLine);
                        }
                        wr.WriteLine("</div>");
                        wr.WriteLine("</div>");

                        /*
                         <div style="display: inline-table">
                         * <p>writecode</p>
                         * <div id="packet1w">
                         * getString();<br />
                         * getInt();<br />
                         * getInt();
                         * </div>
                         * </div>*/
                        //readcode
                        wr.WriteLine("<div>");
                        divID = string.Format("packet{0}r", packetPoint);
                        wr.WriteLine("<a onclick=\"alternativeVisible('" + divID + "');\" href=\"javascript:void(0)\">反序列化代码</a>");
                        wr.WriteLine("<div id=\"{0}\" style=\"display:none\">", divID);
                        foreach (AbsField field in packet.GenerateFieldList())
                        {
                            wr.WriteLine("{0}{1}", field.GenerateDeserializeCode(), TextHelper.HtmlNewLine);
                        }
                        wr.WriteLine("</div>");
                        wr.WriteLine("</div>");


                        wr.WriteLine("</div>");
                        packetPoint++;
                    }

                    wr.WriteLine("</body>");
                    wr.WriteLine("</html>");
                }
            }
        }

        private static XElement GenerateHtmlTable(XElement element, string guid)
        {
            XElement result = new XElement("table",
                new XAttribute("border", "3px"));
            if (!string.IsNullOrEmpty(guid))
            {
                result.Add(new XAttribute("id", guid),
                    new XAttribute("style", "display:none;padding-left:30px"));
            }

            result.Add(
            new XElement("tr",
                new XElement("td", "Name"),
                new XElement("td", "Type"),
                new XElement("td", "Description")
                )
            );

            foreach (XElement field in element.Elements("field"))
            {

                XElement row = GenerateHtmlRow(FieldFactory.CreateField(field));
                if (field.HasElements)
                {
                    //实现点击该行显示或隐藏它的嵌套信息
                    guid = Guid.NewGuid().ToString();
                    row.Add(new XAttribute("onclick", "alternativeVisible('" + guid + "');"));
                    row.Add(new XAttribute("style", "color: Red"));
                }

                result.Add(row);
                if (field.HasElements)
                {
                    result.Add(new XElement("tr",
                        new XElement("td",
                            new XAttribute("colspan", 3),
                            GenerateHtmlTable(field, guid))));
                }
            }

            return result;
        }

        private static XElement GenerateHtmlRow(AbsField f)
        {
            XElement result = new XElement("tr",
                    new XElement("td", f.FieldName),
                    new XElement("td", f.FieldType),
                    new XElement("td", f.Description)
                    );

            return result;
        }
    }
}
